OpenXava génère une interface utilisateur par défaut à partir du modèle. Dans beaucoup de cas simples, ceci est suffisant, mais parfois, il est nécessaire de modéliser avec précision le format de l'interface utilisateur ou des vues. Ce chapitre explique comment.
Mise en page
L'annotation @View est utilisée dans une entité ou une classe embarquée pour définir la mise en page de ses membres (propriétés, référence, collections, ...) dans l'interface utilisateur. La syntaxe de l'annotation @View est la suivante :
@View(
name="name", // 1
members="members", // 2
extendsView="view"// 3 New in v3.1.2)publicclass MyEntity {
name (optionnel). Le nom (name) identifie la vue et peut être utilisé à d'autres endroits d'un projet OpenXava (par exemple dans application.xml) ou dans une autre entité. Si la vue n'a pas de nom, il est assumé que la vue est celle par défaut, c'est-à-dire que celle qui est la plus naturelle pour la l'affichage des objets de ce type. Please, transalte to French: If the name is Simple or Search this view will be used by default to create the search dialog (since v4m4).
members (optionnel). Indique les membres à afficher ainsi que la mise en page dans l'interface utilisateur. Par défaut, tous les membres sont affichés (sauf les cachés) dans l'ordre dans lesquels ils ont été déclarés dans le modèle. A l'intérieur des membres, vous pouvez utiliser des éléments de section et de groupe pour la mise en page. En outre vous pouvez déclarer des actions qui seront présentées sous forme de liens qui déclencheront l'action.
extendsView (optionnel): (New in v3.1.2) All the members in the extendsView view are automatically included in the current one. See view inheritance.
Il est possible de définir plusieurs vues avec l'annotation @Views. Dans ce cas, par défaut (si @View n'est pas utilisé), tous les membres sont affichés dans l'ordre du modèle et un membre par ligne. Par exemple, le modèle suivant :
Vous pouvez constater que les membres sont séparés par des virgules et des points-virgules. Ceci est utilisé pour gérer la position des membres. Avec la virgule, le membre suivant est placé sur la même ligne, à la suite (sur la droite) et avec le point-virgule, le membre suivant est placé en-dessous (sur la ligne suivante). Donc, la vue définie ci-dessus produit l'affichage suivant :
Groupes
Avec les groupes, vous pouvez assembler des propriétés liées et appliquer un effet visuel. Pour définir un groupe, il suffit d'indiquer son nom, suivi des membres qui le composent placés entre crochets, comme ceci :
@View(members=
"id [ zoneNumber, officeNumber, number ];" +
"name")
Dans ce cas, le résultat affiché est le suivant :
Vous pouvez voir les trois propriétés du groupe affichées dans un cadre et le nom (name) en dehors. Le point-virgule avant le nom (name) fait apparaître ce dernier en dessous, sinon la propriété apparaîtrait à droite du cadre. Vous pouvez placer plusieurs groupes dans une vue :
Dans ce cas, les groupes sont affichés l'un contre l'autre :
Si vous souhaitez les placer l'un au-dessus de l'autre, vous devez utiliser le point-virgule après le premier groupe, comme ceci :
Dans ce cas, la vue sera affichée ainsi :
Les groupes imbriqués sont également possible. Cette fonction est très pratique car elle permet de mettre en page simplement les éléments de l'interface utilisateur de manière flexible. Par exemple, une vue pourrait être définie ainsi :
sera affichée ainsi :
ce qui, vous l'avouerez n'est pas très élégant. Il serait plus judicieux d'aligner les données en colonnes. Voici comment définir la vue :
Notez l'utilisation de [# à la place de [. Et voici le résultat :
Grâce à l'ajout du #, les membres sont alignés en colonnes. Cette fonction est aussi disponible pour les sections (voir ci-dessous) (Please, translate the next sentence to French) and for members, that is for the root view (new in v4.7.1). Moreover, if you put alignedByColumns=true (new in v4.7.1) in xava.properties all elements are aligned by column even if you do not specify # in the view.
Sections
De plus, les membres peuvent être organisés en sections. Pour définir une section, il suffit de d'indiquer le nom de la section suivi des membres entre accolades. Voyons un exemple tiré de l'entité Invoice (facture) :
Le résultat dans l'interface utilisateur sera celui-ci :
Les sections sont affichées comme des onglets sur lesquels l'utilisateur peut cliquer pour voir le contenu de la section. Vous pouvez observer comment des membres de tous types sont affichés (pas seulement des propriétés). Ainsi, customer (client) est une référence, details (détails) et deliveries (livraisons) sont des collections. Les sections imbriquées sont aussi possibles, par exemple :
Pour cette définition, vous obtiendrez l'interface utilisateur suivante :
Comme dans le cas des groupes, les sections disposent du marqueur # pour l'alignement par colonnes, comme pour les groupes :
You are invited to translate this section to French.
On defining a new view you can inherit the members and layout of an already existing view. In this way, you can avoid copy & pase, and at the same time you keep your code shorter and easier to update.
This is done using extendsView. For example if you have a view like the next one:
and you will have the next view:
As you see the members of VerySimple view are included automatically in Simple view, and the own members of view are added at the end.
In this case you extend a view of the same entity, but you can also extend a view of the parent entity, if you are using JPA inheritance. That is, if you have an entity called Programmer:
As you can see, the way to extends a view of the superclass is using the super prefix for extendsView. In this case the WithSections view of the JavaProgrammer entity will have all the members of the WithSections view of Programmer entity plus its own ones.
Look the aspect of WithSections view of JavaProgrammer:
If you want to extend the default view (the default view is the view with no name) just use the word DEFAULT as name for extendsView. As in the next example:
The Complete view will have all the members of default view (name, sex, mainLanguage, favouriteFramework, experiences) plus frameworks.
View inheritance only applies to members and their layout. Actions, events and other refinements done at member level are not inherited.
Philosophie de mise en page
Cela vaut la peine de remarquer que nous parlons de groupes à la place de cadres et de sections à la place d'onglets. OpenXava essaye de garder un haut niveau d'abstraction, c'est-à-dire, un groupe est un ensemble de membres liés sémantiquement et les sections permettent de séparer les données en parties. Ceci est pratique lorsqu'il y a beaucoup de données qui ne peuvent pas être affichées simultanément. Le fait que les groupes soient affichés comme des cadres et les sections comme des onglets n'est qu'une affaire d'implémentation. Par exemple, OpenXava pourrait choisir (éventuellement dans le futur) d'afficher les sections (par exemple) sous forme d'arbre ou un élément analogue.
Règles pour les annotations de vue
Vous pouvez marquer un membre (propriété, référence ou collection) avec plusieurs annotations qui affinent le mode d'affichage et le comportement. En outre, vous pouvez spécifier sur quelles vues ces annotations auront un effet. Par exemple, si vous avez une entité comme celle-ci :
De cette façon, la propriété name (nom) sera en lecture seule dans toutes les vues. Toutefois, vous pourriez souhaiter que cette propriété ne soit en lecture seule que pour les vues B et C. Dans ce cas, vous pourriez annoter la propriété de cette manière :
En utilisant l'attribut notForViews, vous indiquez les vues dans lesquelles la propriété name (nom) ne sera pas en lecture seule. Le mot-clé DEFAULT est utilisé pour référencer la vue par défaut (celle sans nom).
Quelques annotations peuvent avoir une ou plusieurs valeurs. Par exemple, pour indiquer quelle vue du type référencé sera utilisée pour afficher une référence, vous utilisez l'annotation @ReferenceView :
@ReferenceView("Simple")private Seller seller;
Dans ce cas, le seller (vendeur) est affiché avec la vue Simple, définit dans l'entité Seller. Que se passe-t-il si vous souhaitez utiliser la vue Simple de Seller uniquement pour la vue B de Customer. C'est simple :
A présent, examinons le cas où l'on souhaite afficher la vue Simple de Seller pour la vue B de Customer, la vue VerySimple (très simple) de Seller pour la vue A de Seller. Dans ce cas, il faut utiliser plusieurs @ReferenceView groupés dans une annotation @ReferenceViews, ainsi :
Ces règles s'appliquent à toutes les annotations de ce chapitre, sauf les annotations @View et @Views.
Personnalisation des propriétés
Vous pouvez affiner l'affichage et le comportement d'une propriété dans une vue en utilisant les annotations suivantes :
@ReadOnly // 1
@LabelFormat // 2
@DisplaySize // 3
@OnChange // 4
@Action// 5
@Editor // 6
@LabelStyle // 7 New in v4m4private type nomPropriete;
Toutes ces annotations suivent les règles d'annotations et sont toutes optionnelles. OpenXava assume une valeur par défaut correcte si l'annotation est absente.
@ReadOnly (OX). Si vous marquez une propriété avec cette annotation, elle ne sera jamais éditable par l'utilisateur final dans cette vue. Une alternative à l'emploi de cette annotation est de contrôler la fonction d'édition de la propriété de manière programmatique en utilisant org.openxava.view.View.
@LabelFormat (OX). Donne le format du libellé de la propriété. Sa valeur peut être l'une définit par LabelFormatType (NORMAL, SMALL ou NO_LABEL).
@DisplaySize (OX). La taille en nombre de caractères de l'éditeur dans l'interface graphique utilisé pour cette propriété. L'éditeur n'affiche que les caractères spécifiés par @DisplaySize, mais permet à l'utilisateur de saisir autant de caractères que la taille de la propriété le permet. Si cette annotation n'est pas présente, c'est la taille de la propriété qui est utilisée.
@OnChange (OX). Action à exécuter lorsque la valeur de la propriété change. Une seule annotation @OnChange par propriété est permis.
@Action (OX). Actions (affichées sous forme de liens, boutons ou images) associées visuellement à cette propriété et que l'utilisateur peut exécuter. Il est possible de définir plusieurs actions pour chaque vue.
@Editor (OX). Nom de l'éditeur utilisé pour afficher la propriété dans cette vue. L'éditeur doit être déclaré dans OpenXava/xava/default-editors.xml ou xava/editors.xml de votre projet.
@LabelStyle (OX): Please, translate to French: (New in v4m4): Style to display the label of this property. It has the predefined styles 'bold-label', 'italic-label' and 'reverse-label'; though you can use your own custom style if you define it in a CSS file.
Format des libellés
Voici un exemple simple d'utilisation de l'annotation @LabelFormat :
Dans ce cas, le code zip (numéro postal) est affiché ainsi :
Le format @LabelFormat.NORMAL est le style par défaut, c'est-à-dire un libellé normal sur la gauche et le format @LabelFormat.NO_LABEL n'affiche simplement aucun libellé. Please, translate the next sentence to French: Since v4m4 you can use defaultLabelFormat in xava.properties to specify the label format to be used when @LabelFormat is omitted.
Evénement de modification de la valeur d'une propriété
Si vous souhaitez réagir à un événement déclenché par un changement de valeur d'une propriété, vous pouvez utiliser l'annotation @OnChange comme ceci:
L'action doit implémenter l'interface IOnChangePropertyAction même s'il est plus pratique d'étendre la classe OnChangePropertyBaseAction (1). A l'intérieur de l'action, la méthode getNewValue() (2) est disponible pour récupérer la nouvelle valeur de la propriété et la méthode getView() (3) permet d'accéder dans le code à l'instance de la class View (la vue courante contenant les valeurs, les éditeurs et tous les composants d'affichage).
Actions d'une propriété
Vous pouvez également associer une action (@Action) à une propriété que l'utilisateur peut directement cliquer:
Dans ce contexte, plutôt que spécifier une classe, vous devez spécifier l'identifiant de l'action défini par le nom du contrôleur suivi du nom de l'action. L'action doit être enregistrée dans le fichier controllers.xml de cette façon :
<controllername="Delivery">
...
<actionname="generateNumber"hidden="true"class="org.openxava.test.actions.GenerateDeliveryNumberAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --></action>
...
</controller>
Les actions sont affichées comme des liens ou des images à côté de la propriété, comme ceci :
Par défaut, le lien de l'action n'est présent qui si la propriété est éditable, mais si la propriété est en lecture seule (@ReadOnly) ou calculée, il est toujours présent. Il est possible de spécifier l'attribut alwaysEnabled à true (vrai) pour que l'action soit toujours active, même si la propriété n'est pas éditable :
Une implémentation simple mais instructive. Vous pouvez utiliser n'importe quelle action enregistrée dans controllers.xml et son comportement est celui de toutes les actions dans OpenXava. Vous pouvez apprendre plus sur les actions en consultant le chapitre 7. Comme option, vous pouvez aussi implémenter l'interface IPropertyAction (ceci n'est disponible que pour les actions de propriétés déclarées avec l'annotation @Action), afin d'injecter le conteneur de la vue et le nom de la propriété dans l'action par OpenXava. L'action ci-dessus pourrait être réécrite ainsi :
L'action implémente IPropertyAction (1) ce qui rend obligatoire l'implémentation des méthodes setProperty() (3) et setView() (4), ces valeurs étant injectées dans l'objet action avant l'appel à la méthode execute() dans laquelle elles peuvent être utilisées (2). Dans ce cas, vous n'êtes pas obligé(e) d'injecter l'objet xava_view dans la définition de l'action dans controllers.xml. La vue injectée dans setView() (4) est la vue intérieure qui contient la propriété. Par exemple, si la propriété fait partie d'une vue d'agrégat, cette vue est la vue de l'agrégat et non la vue principale du module. Ainsi, vous pouvez utiliser des actions plus réutilisables.
Sélection d'un éditeur
Un éditeur est en charge de l'affichage de la propriété pour l'utilisateur et permet à ce dernier d'éditer la valeur. OpenXava utilise par défaut l'éditeur associé au stéréotype ou au type de la propriété, mais vous pouvez un éditeur concret pour l'affichage de la propriété en utilisant l'annotation @Editor.
Par exemple, OpenXava utilise un combo (liste déroulante) pour éditer des propriétés de type enum, mais si vous voulez afficher une propriété de ce type dans une vue particulière en utilisant un bouton radio, vous pouvez définir cette vue ainsi :
@Editor(forViews="TypeWithRadioButton", value="ValidValuesRadioButton")privateType type;publicenumType{ NORMAL, STEADY, SPECIAL };
Dans ce cas, pour afficher/éditer la propriété, l'éditeur ValidValuesRadioButton sera utilisé à la place de celui par défaut. ValidValuesRadioButton est défini dans OpenXava/xava/default-editors.xml comme suit :
Cet éditeur est inclus dans OpenXava, mais vous pouvez créer vos propres éditeurs avec du code JSP personnalisé et les déclarer dans le fichier xava/editors.xml de votre projet.
Cette fonction permet de changer l'éditeur d'une seule vue. Si vous souhaitez changer l'éditeur d'un type, d'un stéréotype ou d'une propriété d'un modèle au niveau de l'application, il est recommandé de le faire en utilisant le fichier xava/editors.xml.
Personnalisation des références
Vous pouvez affiner l'aspect visuel d'une référence et son comportement dans une vue en utilisant les annotations suivantes :
@ReferenceView // 1
@ReadOnly // 2
@NoFrame // 3
@NoCreate // 4
@NoModify // 5
@NoSearch // 6
@AsEmbedded // 7
@SearchAction // 8
@SearchListCondition // 9 New in v4m4
@DescriptionsList // 10
@LabelFormat // 11
@Action// 12
@OnChange // 13
@OnChangeSearch // 14
@Editor // 15 New in v3.1.3
@LabelStyle // 16 New in v4m4
@Collapsed // 17 New in v5.0
@ManyToOne
private type nomReference;
Toutes ces annotation suivent les règles pour les annotations et sont optionnelles. OpenXava assume toujours une valeur par défaut correcte si elles sont omises.
@ReferenceView (OX). Si vous omettez cette annotation, la vue par défaut de la référence est utilisée. Avec cette annotation vous pouvez spécifier une vue alternative à utiliser.
@ReadOnly (OX). Si vous utilisez cette annotation, la référence ne sera jamais éditable par l'utilisateur final dans cette vue. Une alternative est de changer la possibilité d'éditer la référence dans le code en utilisant les instance de org.openxava.view.View.
@NoFrame (OX). Indique si la référence ne doit pas être affichées dans un cadre. Par défaut, les références sont affichées dans un cadre.
@NoCreate (OX). Par défaut, l'utilisateur peut créer de nouveaux objets du type référencé à partir d'ici. Avec cette annotation, cela ne sera plus possible.
@NoModify (OX). Par défaut, l'utilisateur peut modifier l'objet courant du type référencé à partir d'ici. Avec cette annotation, cela ne sera plus possible.
@NoSearch (OX). Par défaut, l'utilisateur a la possibilité de chercher des référence du même type dans une liste avec les filtres, etc.. Avec cette annotation, cela ne sera plus possible.
@AsEmbedded (OX). Par défaut, dans le cas d'une référence marquée comme embarquée, l'utilisateur peut éditer et créer ses données, alors que dans le cas d'une référence à une entité, l'utilisateur ne peut que sélectionner une entité existante. Si vous indiquez l'annotation @AsEmbedded, l'interface utilisateur des références aux entités se comportera comme une référence embarquée, permettant à l'utilisateur de créer une références et d'en éditer les propriété directement. Cette annotation n'a pas d'effet dans le cas de références embarquées. Attention, si vous supprimez une entité, ses entités référencées ne seront pas supprimées, même s'ils sont affichés avec l'annotation @AsEmbedded.
@SearchAction (OX) Vous permet de spécifier votre propre action pour la recherche lorsque l'utilisateur clique sur l'action correspondante. Seulement une annotation de ce type est permise par vue.
@SearchListCondition (OX): (New in v4m4)(Please, translate this to French) Condition to be used for listing the selectable elements that can be used as a reference.
@DescriptionsList (OX). Affiche les données comme une liste de descriptions, typiquement un combo (liste déroulante). Très utile lorsqu'il n'y a que peu de références parmi lesquelles choisir.
@LabelFormat (OX). Format de l'affichage du libellé de la référence. Ceci n'est utilisé que si la référence est affichée à l'aide de l'annotation @DescriptionsList. L'annotation fonctionne comme pour les propriétés.
@Action (OX). Actions (affichées comme liens, boutons, images, etc.) associées visuellement à cette référence et que l'utilisateur final peut exécuter. L'annotation fonctionne comme pour les propriétés. Vous pouvez définir plusieurs actions pour chaque référence dans la même vue.
@OnChange (OX). Action à exécuter lorsque la valeur de la référence change. Une seule annotation @OnChange est permise par référence.
@OnChangeSearch (OX). Permet de spécifier une recherche personnalisée lorsque l'utilisateur entre une nouvelle clé. Une seule annotation par vue est permise.
@Editor (OX): (New in v3.1.3)(Please, translate this to French) Name of the editor to use for displaying the reference in this view. The editor must be declared in OpenXava/xava/default-editors.xml or xava/editors.xml of your project.
@LabelStyle (OX): Please, translate to French: (New in v4m4) Style to display the label of the reference. It only applies if this reference is annotated with @DescriptionsList. Works as in property case.
@Collapsed (OX): Please, translate to French: (New in v5.0) The reference will be shown collapsed for the indicated views. Visually this means that the frame surrounding the reference view will be initially closed. Later the user will be able to set his preferences by clicking on the expansion icon.
Si vous n'utilisez aucune des ces annotations, OpenXava affiche une référence avec la vue par défaut. Par exemple, si vous avez une référence définie ainsi :
@ManyToOne
private Family family;
vous obtiendrez une vue telle que celle-ci :
Sélection de la vue
La personnalisation la plus simple est la sélection de la vue que vous souhaitez pour la représentation de l'objet référencé. Ceci est réalisé à l'aide de l'annotation @ReferenceView :
Ainsi, au lieu d'afficher la vue par défaut de Invoice (qui montre toutes les membres de l'objet), OpenXava utilisera la vue suivante :
Personnalisation du cadre
Si vous combinez l'annotation @NoFrame avec des groupes, vous pouvez assembler visuellement une propriété qui ne fait pas partie de la référence avec celle-ci, par exemple :
L'utilisateur peut rechercher une nouvelle valeur pour la référence simplement en entrant une nouvelle clé et lorsque le curseur quitte l'éditeur, les données de la référence sont récupérées et affichées. Par exemple. si l'utilisateur entre le chiffre "1" dans le champ numéro de la référence seller (vendeur), le champ nom (et les autres données) du vendeur identifié par "1" sera automatiquement rempli. De même, l'utilisateur peut aussi cliquer sur la loupe, dans quel cas, il accédera à une liste dans laquelle il pourra filtrer, trier, etc., et marquer l'objet souhaité.
Afin de définir une action de recherche personnalisée, il faut utiliser l'annotation @SearchAction de cette manière :
La logique de l'action MySearchAction est de votre ressort. Vous pouvez par exemple affiner l'action de recherche standard en filtrant la liste de références comme ceci :
<controllername="MyReference"><actionname="search"hidden="true"class="org.openxava.test.actions.MySearchAction"image="images/search.gif"><use-objectname="xava_view"/><!-- Not needed since v4m2 --><use-objectname="xava_referenceSubview"/><!-- Not needed since v4m2 --><use-objectname="xava_tab"/><!-- Not needed since v4m2 --><use-objectname="xava_currentReferenceLabel"/><!-- Not needed since v4m2 --></action>
...
</controller>
Vous pouvez en apprendre plus sur les actions au chapitre 7.
Condition for search list (reference, new in v4m4)
Please, translate this section to French
When the user clicks in the lantern he go to a list where he can filter, order, etc, and mark the wished object. You can use @SearchAction to overwrite completely this behavior, though if you only want to set a custom condition for the list, then using @SearchListCondition is faster. The above example can be rewritten as following:
Si vous n'utilisez pas l'annotation @NoCreate, l'utilisateur bénéficiera d'un lien lui permettant de créer un nouvel objet. Par défaut, lorsque un utilisateur active ce lien, une vue par défaut de l'objet référencé est affichée dans laquelle il peut entrer les valeurs puis cliquer sur un bouton qui crée l'objet. Si vous souhaitez définir des actions personnalisées (parmi lesquels votre action personnalisée de création) dans le formulaire utilisé pour créer un nouvel objet, vos devez avoir défini un contrôleur dont le nom est identique au composant mais avec le suffixe Creation. Si OpenXava trouve ce contrôleur, il l'utilise à la place de celui par défaut utilisé pour la création de l'objet référencé. Par exemple, vous pouvez définir dans votre fichier controllers.xml :
<!--Parce que son nom est WarehouseCreation (nom du modèle + Creation) il est utilisépar défaut pour créer la référence, au lieu de NewCreation.L'action 'new' est exécutée automatiquement.--><controllername="WarehouseCreation"><extendscontroller="NewCreation"/><actionname="new"hidden="true"class="org.openxava.test.actions.CreateNewWarehouseFromReferenceAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --></action></controller
Dans cet exemple, lorsque l'utilisateur clique sur le lien 'create' (créer), l'utilisateur sera dirigé vers la vue par défaut de Warehouse (entrepôt) et toutes les actions du contrôleur WarehouseCreation seront permises. Si vous avez une action appelée 'new' (nouveau), elle sera exécutée automatiquement avant les autres. Elle peut être utilisée pour initialiser la vue utilisée pour la création du nouvel objet.
Action de modification personnalisée
Si l'annotation @NoModify est absente, l'utilisateur aura une action lui permettant de modifier l'objet référencé. Par défaut, lorsque l'utilisateur choisi cette option, une vue par défaut de l'objet est affichée et l'utilisateur peut modifier les valeurs avant de cliquer sur le bouton de mise à jour. Si vous souhaitez définir des actions personnalisées (parmi lesquels votre action personnalisée de modification) dans le formulaire utilisé pour modifier un objet, vos devez avoir défini un contrôleur dont le nom est identique au composant mais avec le suffixe Modification. Si OpenXava trouve ce contrôleur, il l'utilise à la place de celui par défaut utilisé pour la modification de l'objet référencé. Par exemple, vous pouvez définir dans votre fichier controllers.xml :
<!--Parce que son nom est WarehouseModification (nom du modèle + Modification) il est utilisépar défaut pour modifier la référence, au lieu de Modification.L'action 'search' est exécutée automatiquement.--><controllername="WarehouseModification"><extendscontroller="Modification"/><actionname="search"hidden="true"class="org.openxava.test.actions.ModifyWarehouseFromReferenceAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --></action></controller>
Dans cet exemple, lorsque l'utilisateur clique sur le lien 'modify' (modifier), l'utilisateur sera dirigé vers la vue par défaut de Warehouse (entrepôt) et toutes les actions du contrôleur WarehouseModification seront permises. Si vous avez une action appelée 'search' (recherche), elle sera exécutée automatiquement avant les autres. Elle est utilisée pour initialiser la vue utilisée pour la modification de l'objet.
Liste de descriptions (Combos)
Avec l'annotation @DescriptionsList, vous pouvez indiquer à OpenXava de présenter les références comme des listes de descriptions (actuellement une liste déroulante). Ceci est utile lorsqu'il n'y a que peu d'éléments et que ces éléments possèdent un nom ou une description significative. La syntaxe est la suivante :
descriptionProperties (optionnel). La ou les propriétés à afficher dans la liste. Si cet attribut n'est pas spécifié, la propriété appelée description, descripcion, name ou nombre est assumée. Si l'objet référencé n'a pas de propriété appelée par l'un de ces noms, l'attribut descriptionProperties est requis. Il est possible de mettre plus d'une propriété séparées par des virgules. Pour l'utilisateur finale, les valeurs sont agrégées.
depends (optionnel). Cet attribut est utilisé en combinaison avec condition. Il permet que le contenu de la liste dépende d'une autre valeur affichée dans la vue principale (si vous indiquez simplement le nom d'un membre) ou de la même vue (si vous indiquez this. suivi du nom du membre).
condition (optionnel). Permet de spécifier une condition (dans un style SQL) pour filtrer les valeurs qui sont présentées dans la liste de descriptions.
orderByKey (optionnel). Par défaut, les données sont triées par la description. Toutefois, si vous mettez cette attribut à true (vrai), la liste sera triée selon la clé.
order (optionnel). Permet de spécifier un tri (dans un style SQL) pour les valeurs affichées dans la liste de descriptions.
forTabs (optionnel): Please, translate to French: (New in v4m4) Allows to specify multiple tab names separated by commas. If any of the properties from descriptionProperties is in any of these tabs the filter part will be shown with a description list.
notForTabs (optionnel): Please, translate to French:(New in v4m4) Allows to specify multiple tab names separated by commas. If any of the properties from descriptionProperties is in any of these tabs the filter part will continue to be displayed like a plain property.
qui affiche les référence des entrepôts disponibles (Warehouse) ainsi :
Dans cette exemple, tous les entrepôts sont affichés, même si en réalité la condition de base (baseCondition) et le filtre (filter) sont spécifiés dans l'annotation @Tab de l'entité Warehouse. Vous pouvez apprendre plus sur la gestion des listes dans le chapitre 5.
Si vous souhaitez, par exemple, afficher une liste déroulante (combo) avec des catégories (Family) de produits et que lorsque l'utilisateur en choisit une, une autre liste déroulante soit remplie avec des sous-catégories (Subfamily) de la catégorie choisie, une implémentation de cette fonctionnalité pourrait ressembler à ceci :
Deux listes déroulantes sont affichées, l'une avec toutes les catégories et l'autre vide. Lorsque l'utilisateur choisi une catégorie, la seconde liste et remplie avec toutes les sous-catégories.
Dans le cas de la catégorie (Family), la propriété description de Family est utilisée puisque la propriété par défaut à afficher est 'description' ou 'name'. les données sont triées par clé et non par description (1). Dans le cas de la sous-catégorie (Subfamily) (2), le lien pour créer une nouvelle sous-catégorie n'est pas montré et la propriété à afficher est description (ce qui pourrait par ailleurs être omis).
Avec l'attribut depends (4) vous rendez cette liste déroulante dépendante de la référence family. Lorsqu'une modification de la référence family survient dans l'interface graphique, la liste de descriptions est remplie en appliquant la condition déclarée par l'attribut condition (5) qui envoie la nouvelle valeur de family. Les entrées sont triés par la propriété description en ordre descendant (6).
Dans les attributs condition et order, vous placez le nom de la propriété à l'intérieur de ${} et les arguments sont déclarés par un point d'interrogation (?). Les opérateurs de comparaison sont les opérateurs SQL. New in v3.0.3:(Please, translate to French) Qualified properties are allowed for condition and order even if they are not in descriptionProperties. That is, you can write a condition like this:
(Please, translate to French) You can define complex conditions using JPQL (new in v4.5, before v4.5 SQL was used):
@DescriptionsList(
condition="e.thing.number = (SELECT t.number FROM Thing t WHERE t.name = 'CAR')")private Subfamily subfamily;
(Please, translate to French) As you can see in the example above, with JPQL (new in v4.5) you can use e.propertyName as alternative to ${propertyName}.
Vous pouvez aussi spécifier plusieurs propriétés qui font partie de la description :
Dans ce cas, la concaténation des propriétés description, level (niveau) et name (nom) sera utilisée dans la liste déroulante. Vous pouvez également voir l'utilisation de propriétés qualifiées (level.description).
Si vous utilisez l'annotation @ReadOnly dans une référence annotée avec @DescriptionList, la description (dans ce cas, level.description + name) est affichée comme une simple propriété textuelle à la place de la liste déroulante.
Evénement de modification de la valeur d'une référence
Si vous avez besoin de réagir à un changement de valeur de la référence, vous pouvez déclarer une action ainsi:
Dans ce cas, votre action est à l'écoute du changement du numéro de transporteur (carrier). Le code à exécuter est le suivant :
packageorg.openxava.test.actions;importorg.openxava.actions.*;/**
* @author Javier Paniza
*/publicclass OnChangeCarrierInDeliveryAction
extends OnChangePropertyBaseAction {// 1publicvoid execute()throwsException{if(getNewValue() == null)return;
getView().setValue("remarks", "The carrier is " + getNewValue());
addMessage("carrier_changed");}}
L'action implémente l'interface IOnChangePropertyAction par le biais de l'héritage de OnChangePropertyBaseAction (1), même si c'est une référence. La nouvelle valeur de la propriété clé de la référence est passée comme paramètre, dans ce cas, carrier.number. Le reste est identique au fonctionnement pour les propriétés.
Recherche d'une référence lors de l'événement de modification
L'utilisateur peu chercher la valeur d'une référence simplement en entrant sa clé. Par exemple, s'il existe une référence à l'entité Subfamiliy (sous-catégorie), l'utilisateur peut entrer le numéro de sous-catégorie et les données de celle-ci sont automatiquement chargées dans l'interface utilisateur. Ceci est réalisé à l'aide de l'action par défaut qui exécute la recherche à la modification de la valeur. Vous pouvez spécifier votre propre action de recherche lorsque la clé change en utilisant l'annotation @OnChangeSearch, comme ceci :
L'action est exécutée pour effectuer la recherche à la place de l'action standard lorsque l'utilisateur change le numéro de sous-catégorie. Le code qui est exécuté est le suivant :
L'action implémente l'interface IOnchangePropertyAction par le biais de l'héritage de OnChangeSearchAction (1), même si c'est une référence. La nouvelle valeur de la propriété clé de la référence est passée comme paramètre, dans ce cas, subfamily.number. Ceci est un exemple d'affinage du comportement d'une recherche après modification, car elle hérite de OnChangeSearchAction, qui est l'action par défaut pour la recherche, et appelle super.execute(). Il est également possible de créer une action normale en étendant OnChangePropertyBaseAction par exemple, surchargeant complètement la logique de recherche.
Choosing an editor (reference, new in v3.1.3)
Please, translate this section to French
An editor display the reference to the user and allows him to edit its value. By default, the editor OpenXava uses for references is a detailed view inside a frame (the standard way) or a combo (if you use @DescriptionsList), but you can specify your own editor to display a concrete reference using @Editor.
For example, if you have a reference to a Color entity and you want to display it in some particular entity or view using a custom user interface, such as a radio buttons group with available colors, you can do it in this way:
In this case the ColorRadioButtons editor will be used for displaying/editing, instead of the default one. You must define your ColorRadioButton editor in the xava/editors.xml file of your project:
Also you have to write the JSP code for your editor in colorRadioButonsEditor.jsp.
This feature is for changing the editor for a concrete reference in a concrete entity only, or even only in one view of that entity (using @Editor(forViews=)). If you want to change the editor for all references to certain entity type at application level then it's better to configure it using xava/editors.xml file.
Learn more on Editors for references section of chapter 9.
Personnalisation des collections
Vous pouvez influencer l'aspect visuel et le comportement d'une collection @OneToMany/@ManyToMany dans une vue en utilisant les annotations suivantes :
@CollectionView // 1
@ReadOnly // 2
@EditOnly // 3
@NoCreate // 4
@NoModify // 5
@AsEmbedded // 6
@ListProperties // 7
@RowStyle // 8
@EditAction // 9
@ViewAction // 10
@NewAction // 11
@SaveAction // 12
@HideDetailAction // 13
@RemoveAction // 14
@RemoveSelectedAction // 15
@ListAction // 16
@RowAction // 17 New in v4.6
@DetailAction // 18
@OnSelectElementAction // 19 New in v3.1.2
@Editor // 20 New in v3.1.3
@SearchListCondition // 21 New in v4m4
@Tree // 22 New in v4m4
@Collapsed // 23 New in v5.0
@OneToMany/@ManyToMany
privateCollection collectionName;
Please translate to French: And the next annotations for a @ElementCollection (new in v5.0):
@ListProperties // 7
@Editor // 20 New in v3.1.3
@Collapsed // 23 New in v5.0
@ElementCollection
privateCollection collectionName;
Toutes ces annotations suivent les règles pour les annotations de vues et sont optionnelles. OpenXava assume toujours une valeur correcte lorsqu'elles sont omises.
@CollectionView (OX) La vue de l'objet référencé (un élément de la collection) qui est utilisée pour afficher le détail. Par défaut, la vue par défaut est utilisée.
@ReadOnly (OX) Si vous utilisez cette annotation, l'utilisateur final ne peut que voir les éléments de la collection. Il ne peut ni ajouter, ni supprimer, ni modifier les éléments de la collection.
@EditOnly (OX) Si vous utilisez cette annotation, l'utilisateur peut modifier des éléments existants, mais pas ajouter ou supprimer des éléments de la collection.
@NoCreate (OX) Si vous utilisez cette annotation, l'utilisateur n'aura pas le lien pour créer de nouveaux objets du type référencé. Ceci ne s'applique pas aux collections embarquées.
@NoModify (OX) Si vous utilisez cette annotation, l'utilisateur n'aura pas le lien pour modifier les objets du type référencé. Ceci ne s'applique pas aux collections embarquées.
@AsEmbedded (OX) Par défaut, les collections embarquées (avec un type de cascade REMOVE ou ALL) permettent à l'utilisateur de créer et modifier des éléments, tandis que les collections d'entités traditionnelles ne permettent que de choisir une entité existante pour l'ajouter (ou l'enlever de) à la collection. Si vous utilisez l'annotation @AsEmbedded, la collection se comporte comme une collection embarquée même si elle n'a pas les types de cascade REMOVE ou ALL, permettant ainsi à l'utilisateur d'ajouter ou éditer des objets directement. Cette annotation n'a pas d'effet pour les collections embarquées.
@ListProperties (OX) Indique les propriétés à afficher dans la liste de la collection. Vous pouvez qualifier les propriétés. Par défaut, toutes les propriétés persistantes de l'objet référencé sont affichées (à l'exclusion des références et des propriétés calculées). Please, translate the next sentences to French: The suffix + (new in v4.1) can be added to a property name to show the sum of the column at bottom, like in the tabs. The column summation is not allowed in calculated collections and element collections.
@RowStyle (OX) Permet de donner un style spécial à certaines lignes. Cette annotation fonctionne de la même manière que pour la vue liste des modules. Elle ne fonctionne pas pour les collections calculées et il est possible de définir plusieurs annotation @RowStyle pour chaque vue.
@EditAction (OX) Permet de définir une action personnalisée pour initier l'édition d'un élément de la collection. Cette action est celle affichée dans chaque ligne de la collection, si la collection est éditable. Une seule annotation @EditAction par vue est permise.
@ViewAction (OX) Permet de définir une action personnalisée pour la visualisation d'un objet de la collection. Cette action est celle affichée dans chaque ligne de la collection, si la collection est en lecture seule. Une seule annotation @ViewAction par vue est permise.
@NewAction (OX) Permet de définir une action personnalisée pour initier l'ajout d'un nouvel objet dans la collection. Cette action est celle exécutée après un click sur le lien 'Ajouter'. Une seule annotation @NewAction par vue est permise.
@SaveAction (OX) Permet de définir une action personnalisée pour initier l'enregistrement d'un objet de la collection. Cette action est celle exécutée après un click sur le lien 'Enregistrer le détail'. Une seule annotation @SaveAction par vue est permise.
@HideDetailAction (OX) Permet de définir une action personnalisée pour fermer la vue de détail d'un objet de la collection. Cette action est celle exécutée après un click sur le lien 'Fermer' or closing the dialog. Une seule annotation @HideDetailAction par vue est permise.
@RemoveAction (OX) Permet de définir une action personnalisée pour supprimer un objet de la collection. Cette action est celle exécutée après un click sur le lien 'Supprimer le détail'. Une seule annotation @RemoveAction par vue est permise.
@RemoveSelectedAction (OX) Permet de définir une action personnalisée pour supprimer de la collection un ensemble d'objets sélectionnés dans la liste. Cette action est celle exécutée après un click sur le lien 'Supprimer la sélection'. Une seule annotation @RemoveSelectedAction par vue est permise.
@ListAction (OX) Permet d'ajouter des actions à la vue liste de la collection, en général des actions dont le cadre est la collection entière. Il est possible de définir plusieurs actions de ce type pour chaque vue.
@RowAction (OX): Please, translate to French: (New in v4.6) To add actions in list mode associated to each row; these actions are not present in the button bar of the collection, but only in the rows. It's possible to define several @RowAction for each view.
@DetailAction (OX) Permet d'ajouter des actions à la vue de détail des éléments de la collection, en général des actions dont le cadre est l'objet en cours d'édition. Il est possible de définir plusieurs actions de ce type pour chaque vue.
@OnSelectElementAction (OX): (New in v3.1.2)(Please, translate this to French) To define an action to be executed when an element of the collection is selected or unselected. It's possible to define several @OnSelectElementAction for each view.
@Editor (OX): (New in v3.1.3)(Please, translate this to French) Name of the editor to use for displaying the collection in this view. The editor must be declared in OpenXava/xava/default-editors.xml or xava/editors.xml of your project.
@SearchListCondition (OX): (New in v4m4)(Please, translate this to French) Condition to be used for listing the selectable elements that can be added to the collection. It does not apply to embedded collections.
@Tree (OX): Please, translate to French:(New in v4m4) To indicate that this collection will be displayed using a tree instead of a list.
@Collapsed (OX): Please, translate to French: (New in v5.0) The collection will be shown collapsed for the indicated views. Visually this means that the frame surrounding the collection view will be initially closed. Later the user will be able to set his preferences by clicking on the expansion icon.
Si vous n'utilisez aucune de ces annotations, celle-ci est affichée en utilisant les propriétés persistantes dans le mode liste et la vue par défaut pour présenter le détail de l'objet. Toutefois, dans les scénarios usuels, les propriétés de la liste et du détail sont spécifiés :
La définition ci-dessus est affichée ainsi :
Remarquez comment les propriétés qualifiées sont utilisées dans la liste des propriétés (exemple seller.level.description).
Lorsque l'utilisateur clique sur (édition), la vue Simple de l'entité Customer (client) est affichée. Bien entendu, pour que cela fonctionne, il faut avoir préalablement défini une vue Simple dans l'entité Customer (le modèle des éléments de la collection).
La même vue est utilisée lorsque l'utilisateur clique sur dans une collection embarquée, sinon OpenXava n'affiche pas cette vue et montre plutôt la liste des entités à ajouter. Si la vue Simple de Customer est définie ainsi :
en cliquant pour voir un détail, l'affichage suivant sera généré :
Please, translate to French: Element collections (new in v5.0) do not use @ReferenceView because the data is editable in the collection directly, like an spreadsheet. However, you can use @ListProperties. If you define an element collection in this way:
Dans le fichier controllers.xml, il faut déclarer le contrôleur Invoices.editDetail :
<controllername="Invoice">
...
<actionname="editDetail"hidden="true"image="images/edit.gif"class="org.openxava.test.actions.EditInvoiceDetailAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --></action>
...
</controller>
Dans cet exemple, vous ne faites qu'affiner car votre action étend EditElementInCollectionAction (1). Dans ce cas, vous ne spécifiez qu'une valeur par défaut pour la propriété remarks (remarques). Notez que pour accéder à la vue qui affiche le détail, vous pouvez utiliser la méthode getCollectionElementView() (2).
Il est aussi possible d'enlever l'action d'édition de l'interface utilisateur de cette manière :
Il suffit de spécifier une chaîne de caractère vide comme valeur de l'action. Toutefois, dans la plupart des cas, il est plus aisé de définir la collection avec l'annotation @ReadOnly.
La technique pour affiner une action de vue (l'action pour chaque ligne de la liste) est la même sauf qu'elle est définie par l'annotation @ViewAction au lieu de @EditAction.
Actions de liste et rang personnalisées
S'applique à collection @OneToMany/@ManyToMany Please, translate the next paragraph to French
Use @ListAction to define actions that applies to entire collection and @RowAction(new in v4.6) to define actions for each row. @ListAction and @RowAction are very alike, indeed they are coded in the same way, the difference is that the @ListActions are shown in the button bar while the @RowActions are shown in each row. @ListActions can be also shown in each row if they are defined as in-each-row="true" in controllers.xml.
This is an example:
L'action étend CollectionBaseAction (1). De cette façon, vous pouvez utiliser des méthodes comme getSelectedObjects() (2) qui retourne une collection avec les objets sélectionnés par l'utilisateur. D'autres méthodes utiles sont également disponibles comme getObjects() (tous les éléments de la collection), getMapValues() (les valeurs de la collection dans un format dictionnaire) et getMapsSelectedValues()(les éléments sélectionnés dans un format dictionnaire). Please, translate the next sentence to French: In the case of @RowAction,getSelectedObjects() and getMapsSelectedValues() return an unique element, the one of the row of the action, even if the row is not checked.
Comme dans le cas des actions de détail (voir section suivante), vous pouvez utiliser getCollectionElementView(). Il est aussi possible d'utiliser des actions pour le mode liste comme actions de liste personnalisées.
Actions de liste et rang par défaut
S'applique à collection @OneToMany/@ManyToMany
Si vous voulez ajouter quelques actions de liste personnalisées pour toutes les collections de votre application, vous pouvez créer un contrôleur appelé DefaultListActionsForCollections dans le fichier xava/controllers.xml comme ceci:
De cette manière, toutes les collections auront les actions du contrôleur Print (pour l'exportation vers Excel et la génération de rapports PDF) et votre propre ExportAsXMLAction. Ceci a le même effet que l'annotation @ListAction (référez-vous à la section sur les actions de liste personnalisées) mais s'applique à toutes les collections en une seule fois. Please, translate the next sentence to French: If you want to define default row actions (@RowAction) you can define the controller DefaultRowActionsForCollections (new in v4.6).
Cette fonction ne s'applique pas aux collections calculées.
Actions de détail personnalisées
S'applique à collection @OneToMany/@ManyToMany
Il est également possible d'ajouter des actions personnalisées aux vues de détail utilisées pour modifier chaque élément de la collection. L'annotation @DetailAction permet de réaliser ceci. Ces actions sont applicables à un seul élément de la collection à la fois. Par exemple :
De cette manière, l'utilisateur bénéficiera d'un nouveau lien dans la vue de détail de l'élément de la collection, ici View Product (Voir le produit) :
Vous devez préalablement définir l'action dans le fichier controllers.xml de votre projet :
<controllername="Invoice">
...
<actionname="viewProduct"hidden="true"class="org.openxava.test.actions.ViewProductFromInvoiceDetailAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --><use-objectname="xavatest_invoiceValues"/><!-- Not needed since v4m2 --></action>
...
</controller>
Et puis écrire le code de votre action :
packageorg.openxava.test.actions;importjava.util.*;importjavax.ejb.*;importorg.openxava.actions.*;/**
* @author Javier Paniza
*/publicclass ViewProductFromInvoiceDetailAction
extends CollectionElementViewBaseAction // 1implements INavigationAction {
@Inject // Since v4m2privateMap invoiceValues;publicvoid execute()throwsException{try{
setInvoiceValues(getView().getValues());Object number =
getCollectionElementView().getValue("product.number");// 2Map key = newHashMap();
key.put("number", number);
getView().setModelName("Product");// 3
getView().setValues(key);// Since v4m5 you can
getView().findObject();// use getParentView() instead
getView().setKeyEditable(false);
getView().setEditable(false);}catch(ObjectNotFoundException ex){
getView().clear();
addError("object_not_found");}catch(Exception ex){
ex.printStackTrace();
addError("system_error");}}publicString[] getNextControllers(){returnnewString[]{"ProductFromInvoice"};}publicString getCustomView(){return SAME_VIEW;}publicMap getInvoiceValues(){return invoiceValues;}publicvoid setInvoiceValues(Map map){
invoiceValues = map;}}
Vous pouvez observer que la classe de l'action hérite de CollectionElementViewBaseAction (1) et bénéficie donc d'un accès à la vue qui affiche l'élément courant par la méthode getCollectionElementView() (2). La vue principale est également accessible en utilisant la méthode getView() (3) ou getParentView() (since v4m5). Dans le chapitre 7, vous pouvez avoir plus de détails sur l'écriture des actions.
En outre, en utilisant la vue renvoyée par la méthode getCollectionElementView(), vous pouvez ajouter et supprimer depuis le code des actions de détail et de liste avec les méthodes addDetailAction(), removeDetailAction(), addListAction() et removeListAction() (référez vous à la documentation de l'API de org.openxava.view.View.
Affinage du comportement par défaut de la vue de collection
S'applique à collection @OneToMany/@ManyToMany
En utilisant les annotations @NewAction, @SaveAction, @HideDetailAction, @RemoveAction et @RemoveSelectedAction, vous pouvez affiner le comportement par défaut d'une vue de collection. Par exemple, si vous voulez redéfinir le comportement de l'action d'enregistrer un détail, vous pouvez définir votre vue ainsi :
Bien entendu, vous devez également définir l'action DeliveryDetail.save (Détail de livraison.enregistrer) dans le fichier controllers.xml de votre projet :
<controllername="DeliveryDetail">
...
<actionname="save"class="org.openxava.test.actions.SaveDeliveryDetailAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --></action>
...
</controller>
Et finalement écrire l'implémentation de l'action pour procéder à l'enregistrement :
Le cas le plus commun est d'étendre le comportement par défaut en faisant hériter votre action de la classe originale qui enregistre un élément de la collection (1), c'est-à-dire l'action SaveElementInCollectionElement puis en faisant appel à la méthode super.execute() (2) depuis votre propre méthode execute() avant d'insérer votre code.
Il est également possible d'enlever n'importe laquelle de ces actions de l'interface graphique. Par exemple, vous pouvez définir une collection de cette manière :
Dans ce cas, l'action pour supprimer les éléments sélectionnés de la collectionne sera pas présente dans l'interface utilisateur. Comme vous pouvez le constater, il faut déclarer une chaîne de caractères vide comme nom de l'action.
Action when a collection element is selected (new in v3.1.2)
S'applique à collection @OneToMany/@ManyToMany Please, translate this section to French
You can define an action to be executed when a collection element is selected or unselected. This is accomplished using the @OnSelectElementAction annotation. For example, imagine that you have a collection just like this one:
And you want that when a row is selected the value of the selectedIngredientSize field in the user interface will be updated. Let's code it.
First you have to annotate your collection:
In this simple way (1), and thanks to the @OnSelectElementAction annotation, you say that when the user clicks on the checkbox of the collection row the Formula.onSelectIngredient action will be executed. This action is declared in controllers.xml, in this way:
<controllername="Formula">
...
<actionname="onSelectIngredient"hidden="true"class="org.openxava.test.actions.OnSelectIngredientAction"><use-objectname="xava_view"/><!-- Not needed since v4m2 --></action>
...
</controller>
Now, only remains the code of the OnSelectIngredientAction class:
The easiest way to implement the action is extending from OnSelectElementBaseAction, this allows you to access to the property selected (by means of isSelected(), 2) that indicates wheter the user has selected or unselected the row; and row (using getRow()) that indicates the row number of the affected collection element.
Choosing an editor (collection, new in v3.1.3)
S'applique à collection @OneToMany/@ManyToMany et @ElementCollection Please, translate this section to French
An editor display the collection to the user and allows him to edit its values. By default, the editor OpenXava uses for collections is a list that shows the data in a tabular fashion, allowing to order, filter and paging, but you can specify your own editor to display a concrete collection using @Editor.
For example, if you have a collection of Customer entities and you want to display it in some particular entity or view using a custom user interface, such as a simple list of names, you can do it in this way:
In this case the CustomersNames editor will be used for displaying/editing, instead of the default one. You must define your CustomersNames editor in the xava/editors.xml file of your project:
Also you have to write the JSP code for your editor in customersNamesEditor.jsp.
This feature is for changing the editor for a concrete collection in a concrete entity only, or even only in one view of that entity (using @Editor(forViews=)). If you want to change the editor for all collections to certain entity type at application level then it's better to configure it using xava/editors.xml file.
Learn more on Editors for collections section of chapter 9.
Condition for search list (collection, new in v4m4)
S'applique à collection @OneToMany/@ManyToMany Please, translate this section to French
You can specify a condition to be applied to the list of items available for selection. In the case of non-embedded collections. By using @SearchListCondition you can define a condition only applicable to the search list, furthermore, you can use it along with the forViews and notForViews property to define different criteria for different views (1) as shown in the following code snippet.
Selecting the TreeView editor (1) is enough for displaying the collection as a tree. The properties defined as ids are used for making the label of the treeview, but you can define different properties by specifying the @ListProperties (2) annotation. The items are displayed in the natural order of the collection of the order defined by @OrderBy (3). If the collection entity contains a string property named "path", the treeview editor render the tree using its content; if another property should be used instead, then you must use the @Tree annotation (4) to indicate which property to use.
Path content example
As you can see in the table, the tree is made by concatenating the id separated by "/". Sibling items must have the same path. The editor takes care of the creation and modification of the path property. This will look like this: Please translate the next paragraphs to French
The full syntax for @Tree is:
forViews: Indicates in which views the tree behavior is going to be applied.
notForViews: Views which are excluded from the tree renderization.
pathProperty: Indicates the property to be used as the path, by default points to "path". You can customize this property if the entity path reference is persisted in a property with another name.
idProperties: The tree implementation needs a unique identification for each of the elements displayed. By default the tree implementation use the properties annotated with @Id, but you can define which properties the tree must use as the unique identifier. The defined properties are comma separated.
initialExpandedState: If true the tree is rendered with all nodes expanded.
orderIncrement: If you define a @OrderBy and it represents an integer property type, the Tree implementation uses this field to allow reordering of the tree elements, by default the increment value is 2 and is the minimum allowed. This value allow easy reordering of elements.
pathSeparator: If you use a separator for your path different than the default "/". Then you can set this property to the value that you are using.
Total properties (new in v4.3)
S'applique à collection @OneToMany/@ManyToMany and @ElementCollection Please, translate this section to French
Inside @ListProperties you can define, between square brakets, a set of properties of the parent entity of the collection to be shown in the footer of the collection as total values. That is, if you define a collection in this way:
You get:
Total properties can be used for both persistent and calculated collections. You can add total properties to any property of @ListProperties and they can be of any type, not just numbers. These total properties are from the container entity so you have to use the reference to the container entity as prefix, that is, the prefix of the total properties must match with the mappedBy reference in the case of persistent collections.
Propriétés transientes pour la gestion de l'interface utilisateur
Avec l'annotation @Transient (JPA), vous déclarez une propriété qui n'est pas enregistrée dans la base de donnée, mais que vous souhaitez montrer à l'utilisateur. Vous pouvez utiliser cette fonctionnalité pour fournir des contrôles d'interface utilisateur pour leur permettre de gérer son interface graphique. Un exemple :
Notez que la syntaxe est exactement la même que dans le cas d'une propriété standard d'une entité. Vous pouvez même utiliser un enum et un calculateur par défaut (@DefaultValueCalculator). Après avoir défini la propriété, vous pouvez l'utiliser dans la vue comme d'habitude, par exemple avec l'annotation @OnChange ou en le rendant membre d'une vue.
Actions de vues
En plus d'associer des actions à des propriétés, des références ou des collections, vous pouvez aussi ajouter des actions arbitraires à l'intérieur de votre vue, à n'importe quel endroit. Pour ce faire, vous utilisez le nom qualifié de l'action en utilisant de parenthèses () comme suffixe, de cette manière :
L'effet visuel sera celui-ci :
Le lien 'Change name label' (Changer le libellé du nom) exécutera l'action Customer.changeNameLabel lorsque l'utilisateur cliquera dessus. Si la vue parente de l'action n'est pas éditable, l'action n'est pas affichée. Si vous souhaitez que l'action soit toujours présente, même si la vue n'est pas éditable, vous devez placer le mot-clé ALWAYS entre les parenthèses, comme ici :
La manière standard d'exposer des actions à l'utilisateur est d'utiliser des contrôleurs (actions dans les barres supérieures et/ou inférieures) afin que les contrôleurs soient réutilisables entre les vues, mais parfois, vous devrez avoir une action spécifique pour une vue, et vous souhaiterez l'afficher à l'intérieur de la vue (et non dans la barre d'actions). Pour ces cas, les actions de vue sont utiles. Plus sur les actions au chapitre 7.
Classes transientes : Uniquement pour créer des vues
Dans OpenXava, il n'est pas possible d'avoir une vue générée sans modèle. Ainsi, si vous souhaitez développer une interface utilisateur arbitraire, vous devez créer une classe, ne pas la déclarer comme entité et y définir votre vue.
Une classe transiente n'est pas associée à une table de la base de données, typiquement elle n'est utilisée que pour l'affichage de l'interface graphique et n'est liée à aucune donnée de la base. Une exemple pourrait être le suivant :
packageorg.openxava.test.model;importjavax.persistence.*;importorg.openxava.annotations.*;/**
* Exemple d'une classe de modèle OpenXava transiente (non persistente). <p>
*
* Elle peut être utilisée, par exemple, pour afficher un dialogue,
* ou n'importe quelle autre interface graphique.<p>
*
* Notez qu'elle n'est pas marquée avec @Entity <br>
*
* @author Javier Paniza
*/
@Views({
@View(name="Family1", members="subfamily"),
@View(name="Family2", members="subfamily"),
@View(name="WithSubfamilyForm", members="subfamily"),
@View(name="Range", members="subfamily; subfamilyTo")})publicclass FilterBySubfamily {
@ManyToOne(fetch=FetchType.LAZY) @Required
@NoCreate(forViews="Family1, Family2")
@NoModify(forViews="Family2, WithSubfamilyForm")
@NoSearch(forViews="WithSubfamilyForm")
@DescriptionsLists({
@DescriptionsList(forViews="Family1",
condition="${family.number} = 1", order="${number} desc"),
@DescriptionsList(forViews="Family2",
condition="${family.number} = 2")})private Subfamily subfamily;
@ManyToOne(fetch=FetchType.LAZY)private Subfamily subfamilyTo;public Subfamily getSubfamily(){return subfamily;}publicvoid setSubfamily(Subfamily subfamily){this.subfamily = subfamily;}public Subfamily getSubfamilyTo(){return subfamilyTo;}publicvoid setSubfamilyTo(Subfamily subfamilyTo){this.subfamilyTo = subfamilyTo;}}
Pour définir une classe de modèle transiente, vous n'avez qu'à définir une classe standard Java sans l'annotation @Entity. Vous ne spécifiez pas non plus les annotations de mapping objet-relationnel ni les propriétés comme clé.
Ainsi, vous pouvez développer un dialogue qui peut être utile, par exemple, pour imprimer un rapport des catégories de produits, filtrés par sous-catégorie.
Les classes transientes sont utilisées uniquement avec des modules de détail. (Please, translate the next sentence to French) You can use a transient class without defining a module because a default one is generated, however if you want to generate a portlet for your transient class you must define explicitly a module in application.xml.
Le paquet contenant le classes de modèle transientes doit être le même que celui des classes persistantes.
Avec cette simple astuce, vous pouvez utiliser OpenXava comme un générateur simple et flexible d'interfaces graphiques même si les données ne seront jamais enregistrées.
Table of Contents
Chapitre 4. Vue
OpenXava génère une interface utilisateur par défaut à partir du modèle. Dans beaucoup de cas simples, ceci est suffisant, mais parfois, il est nécessaire de modéliser avec précision le format de l'interface utilisateur ou des vues. Ce chapitre explique comment.Mise en page
L'annotation @View est utilisée dans une entité ou une classe embarquée pour définir la mise en page de ses membres (propriétés, référence, collections, ...) dans l'interface utilisateur. La syntaxe de l'annotation @View est la suivante :- name (optionnel). Le nom (name) identifie la vue et peut être utilisé à d'autres endroits d'un projet OpenXava (par exemple dans application.xml) ou dans une autre entité. Si la vue n'a pas de nom, il est assumé que la vue est celle par défaut, c'est-à-dire que celle qui est la plus naturelle pour la l'affichage des objets de ce type. Please, transalte to French: If the name is Simple or Search this view will be used by default to create the search dialog (since v4m4).
- members (optionnel). Indique les membres à afficher ainsi que la mise en page dans l'interface utilisateur. Par défaut, tous les membres sont affichés (sauf les cachés) dans l'ordre dans lesquels ils ont été déclarés dans le modèle. A l'intérieur des membres, vous pouvez utiliser des éléments de section et de groupe pour la mise en page. En outre vous pouvez déclarer des actions qui seront présentées sous forme de liens qui déclencheront l'action.
- extendsView (optionnel): (New in v3.1.2) All the members in the extendsView view are automatically included in the current one. See view inheritance.
Il est possible de définir plusieurs vues avec l'annotation @Views. Dans ce cas, par défaut (si @View n'est pas utilisé), tous les membres sont affichés dans l'ordre du modèle et un membre par ligne. Par exemple, le modèle suivant :génère cette vue :
Vous pouvez choisir les membres à afficher ainsi que leur ordre à l'aide de l'attribut members :
Dans ce cas, la propriété name n'est pas affichée. Vous pouvez aussi utiliser l'attribut members pour affiner la mise en page :
Vous pouvez constater que les membres sont séparés par des virgules et des points-virgules. Ceci est utilisé pour gérer la position des membres. Avec la virgule, le membre suivant est placé sur la même ligne, à la suite (sur la droite) et avec le point-virgule, le membre suivant est placé en-dessous (sur la ligne suivante). Donc, la vue définie ci-dessus produit l'affichage suivant :
Groupes
Avec les groupes, vous pouvez assembler des propriétés liées et appliquer un effet visuel. Pour définir un groupe, il suffit d'indiquer son nom, suivi des membres qui le composent placés entre crochets, comme ceci :Dans ce cas, le résultat affiché est le suivant :
Vous pouvez voir les trois propriétés du groupe affichées dans un cadre et le nom (name) en dehors. Le point-virgule avant le nom (name) fait apparaître ce dernier en dessous, sinon la propriété apparaîtrait à droite du cadre. Vous pouvez placer plusieurs groupes dans une vue :
Dans ce cas, les groupes sont affichés l'un contre l'autre :
Si vous souhaitez les placer l'un au-dessus de l'autre, vous devez utiliser le point-virgule après le premier groupe, comme ceci :
Dans ce cas, la vue sera affichée ainsi :
Les groupes imbriqués sont également possible. Cette fonction est très pratique car elle permet de mettre en page simplement les éléments de l'interface utilisateur de manière flexible. Par exemple, une vue pourrait être définie ainsi :
Et le résultat sera celui-ci :
Quelquefois, il est utile d'organiser l'affichage des propriétés alignées en colonnes, comme une table. Cette vue :
sera affichée ainsi :
ce qui, vous l'avouerez n'est pas très élégant. Il serait plus judicieux d'aligner les données en colonnes. Voici comment définir la vue :
Notez l'utilisation de [# à la place de [. Et voici le résultat :
Grâce à l'ajout du #, les membres sont alignés en colonnes. Cette fonction est aussi disponible pour les sections (voir ci-dessous) (Please, translate the next sentence to French) and for members, that is for the root view (new in v4.7.1). Moreover, if you put alignedByColumns=true (new in v4.7.1) in xava.properties all elements are aligned by column even if you do not specify # in the view.
Sections
De plus, les membres peuvent être organisés en sections. Pour définir une section, il suffit de d'indiquer le nom de la section suivi des membres entre accolades. Voyons un exemple tiré de l'entité Invoice (facture) :Le résultat dans l'interface utilisateur sera celui-ci :
Les sections sont affichées comme des onglets sur lesquels l'utilisateur peut cliquer pour voir le contenu de la section. Vous pouvez observer comment des membres de tous types sont affichés (pas seulement des propriétés). Ainsi, customer (client) est une référence, details (détails) et deliveries (livraisons) sont des collections. Les sections imbriquées sont aussi possibles, par exemple :
Pour cette définition, vous obtiendrez l'interface utilisateur suivante :
Comme dans le cas des groupes, les sections disposent du marqueur # pour l'alignement par colonnes, comme pour les groupes :
View inheritance (new in v3.1.2)
You are invited to translate this section to French.On defining a new view you can inherit the members and layout of an already existing view. In this way, you can avoid copy & pase, and at the same time you keep your code shorter and easier to update.
This is done using extendsView. For example if you have a view like the next one:
That produces the next UI:
If you want a new view that extends this one just write the next code:
and you will have the next view:
As you see the members of VerySimple view are included automatically in Simple view, and the own members of view are added at the end.
In this case you extend a view of the same entity, but you can also extend a view of the parent entity, if you are using JPA inheritance. That is, if you have an entity called Programmer:
You can reuse the WithSections view in a child class of Programmer:
As you can see, the way to extends a view of the superclass is using the super prefix for extendsView. In this case the WithSections view of the JavaProgrammer entity will have all the members of the WithSections view of Programmer entity plus its own ones.
Look the aspect of WithSections view of JavaProgrammer:
If you want to extend the default view (the default view is the view with no name) just use the word DEFAULT as name for extendsView. As in the next example:
The Complete view will have all the members of default view (name, sex, mainLanguage, favouriteFramework, experiences) plus frameworks.
View inheritance only applies to members and their layout. Actions, events and other refinements done at member level are not inherited.
Philosophie de mise en page
Cela vaut la peine de remarquer que nous parlons de groupes à la place de cadres et de sections à la place d'onglets. OpenXava essaye de garder un haut niveau d'abstraction, c'est-à-dire, un groupe est un ensemble de membres liés sémantiquement et les sections permettent de séparer les données en parties. Ceci est pratique lorsqu'il y a beaucoup de données qui ne peuvent pas être affichées simultanément. Le fait que les groupes soient affichés comme des cadres et les sections comme des onglets n'est qu'une affaire d'implémentation. Par exemple, OpenXava pourrait choisir (éventuellement dans le futur) d'afficher les sections (par exemple) sous forme d'arbre ou un élément analogue.Règles pour les annotations de vue
Vous pouvez marquer un membre (propriété, référence ou collection) avec plusieurs annotations qui affinent le mode d'affichage et le comportement. En outre, vous pouvez spécifier sur quelles vues ces annotations auront un effet. Par exemple, si vous avez une entité comme celle-ci :et que vous souhaitez que la propriété name (nom) soit en lecture seule. Vous pouvez annoter cette propriété ainsi :
De cette façon, la propriété name (nom) sera en lecture seule dans toutes les vues. Toutefois, vous pourriez souhaiter que cette propriété ne soit en lecture seule que pour les vues B et C. Dans ce cas, vous pourriez annoter la propriété de cette manière :
Une autre façon d'obtenir le même résultat :
En utilisant l'attribut notForViews, vous indiquez les vues dans lesquelles la propriété name (nom) ne sera pas en lecture seule. Le mot-clé DEFAULT est utilisé pour référencer la vue par défaut (celle sans nom).
Quelques annotations peuvent avoir une ou plusieurs valeurs. Par exemple, pour indiquer quelle vue du type référencé sera utilisée pour afficher une référence, vous utilisez l'annotation @ReferenceView :
Dans ce cas, le seller (vendeur) est affiché avec la vue Simple, définit dans l'entité Seller. Que se passe-t-il si vous souhaitez utiliser la vue Simple de Seller uniquement pour la vue B de Customer. C'est simple :
A présent, examinons le cas où l'on souhaite afficher la vue Simple de Seller pour la vue B de Customer, la vue VerySimple (très simple) de Seller pour la vue A de Seller. Dans ce cas, il faut utiliser plusieurs @ReferenceView groupés dans une annotation @ReferenceViews, ainsi :
Ces règles s'appliquent à toutes les annotations de ce chapitre, sauf les annotations @View et @Views.
Personnalisation des propriétés
Vous pouvez affiner l'affichage et le comportement d'une propriété dans une vue en utilisant les annotations suivantes :Toutes ces annotations suivent les règles d'annotations et sont toutes optionnelles. OpenXava assume une valeur par défaut correcte si l'annotation est absente.
Format des libellés
Voici un exemple simple d'utilisation de l'annotation @LabelFormat :Dans ce cas, le code zip (numéro postal) est affiché ainsi :
Le format @LabelFormat.NORMAL est le style par défaut, c'est-à-dire un libellé normal sur la gauche et le format @LabelFormat.NO_LABEL n'affiche simplement aucun libellé. Please, translate the next sentence to French: Since v4m4 you can use defaultLabelFormat in xava.properties to specify the label format to be used when @LabelFormat is omitted.
Evénement de modification de la valeur d'une propriété
Si vous souhaitez réagir à un événement déclenché par un changement de valeur d'une propriété, vous pouvez utiliser l'annotation @OnChange comme ceci:Le code à exécuter est le suivant :
L'action doit implémenter l'interface IOnChangePropertyAction même s'il est plus pratique d'étendre la classe OnChangePropertyBaseAction (1). A l'intérieur de l'action, la méthode getNewValue() (2) est disponible pour récupérer la nouvelle valeur de la propriété et la méthode getView() (3) permet d'accéder dans le code à l'instance de la class View (la vue courante contenant les valeurs, les éditeurs et tous les composants d'affichage).
Actions d'une propriété
Vous pouvez également associer une action (@Action) à une propriété que l'utilisateur peut directement cliquer:Dans ce contexte, plutôt que spécifier une classe, vous devez spécifier l'identifiant de l'action défini par le nom du contrôleur suivi du nom de l'action. L'action doit être enregistrée dans le fichier controllers.xml de cette façon :
Les actions sont affichées comme des liens ou des images à côté de la propriété, comme ceci :
Par défaut, le lien de l'action n'est présent qui si la propriété est éditable, mais si la propriété est en lecture seule (@ReadOnly) ou calculée, il est toujours présent. Il est possible de spécifier l'attribut alwaysEnabled à true (vrai) pour que l'action soit toujours active, même si la propriété n'est pas éditable :
L'attribut alwaysEnabled est optionnel et sa valeur par défaut est false (faux). Le code de l'action précédante est le suivant :
Une implémentation simple mais instructive. Vous pouvez utiliser n'importe quelle action enregistrée dans controllers.xml et son comportement est celui de toutes les actions dans OpenXava. Vous pouvez apprendre plus sur les actions en consultant le chapitre 7. Comme option, vous pouvez aussi implémenter l'interface IPropertyAction (ceci n'est disponible que pour les actions de propriétés déclarées avec l'annotation @Action), afin d'injecter le conteneur de la vue et le nom de la propriété dans l'action par OpenXava. L'action ci-dessus pourrait être réécrite ainsi :
L'action implémente IPropertyAction (1) ce qui rend obligatoire l'implémentation des méthodes setProperty() (3) et setView() (4), ces valeurs étant injectées dans l'objet action avant l'appel à la méthode execute() dans laquelle elles peuvent être utilisées (2). Dans ce cas, vous n'êtes pas obligé(e) d'injecter l'objet xava_view dans la définition de l'action dans controllers.xml. La vue injectée dans setView() (4) est la vue intérieure qui contient la propriété. Par exemple, si la propriété fait partie d'une vue d'agrégat, cette vue est la vue de l'agrégat et non la vue principale du module. Ainsi, vous pouvez utiliser des actions plus réutilisables.
Sélection d'un éditeur
Un éditeur est en charge de l'affichage de la propriété pour l'utilisateur et permet à ce dernier d'éditer la valeur. OpenXava utilise par défaut l'éditeur associé au stéréotype ou au type de la propriété, mais vous pouvez un éditeur concret pour l'affichage de la propriété en utilisant l'annotation @Editor.Par exemple, OpenXava utilise un combo (liste déroulante) pour éditer des propriétés de type enum, mais si vous voulez afficher une propriété de ce type dans une vue particulière en utilisant un bouton radio, vous pouvez définir cette vue ainsi :
Dans ce cas, pour afficher/éditer la propriété, l'éditeur ValidValuesRadioButton sera utilisé à la place de celui par défaut. ValidValuesRadioButton est défini dans OpenXava/xava/default-editors.xml comme suit :
<editor name="ValidValuesRadioButton" url="radioButtonEditor.jsp"/>Cet éditeur est inclus dans OpenXava, mais vous pouvez créer vos propres éditeurs avec du code JSP personnalisé et les déclarer dans le fichier xava/editors.xml de votre projet.Cette fonction permet de changer l'éditeur d'une seule vue. Si vous souhaitez changer l'éditeur d'un type, d'un stéréotype ou d'une propriété d'un modèle au niveau de l'application, il est recommandé de le faire en utilisant le fichier xava/editors.xml.
Personnalisation des références
Vous pouvez affiner l'aspect visuel d'une référence et son comportement dans une vue en utilisant les annotations suivantes :Toutes ces annotation suivent les règles pour les annotations et sont optionnelles. OpenXava assume toujours une valeur par défaut correcte si elles sont omises.
Si vous n'utilisez aucune des ces annotations, OpenXava affiche une référence avec la vue par défaut. Par exemple, si vous avez une référence définie ainsi :
vous obtiendrez une vue telle que celle-ci :
Sélection de la vue
La personnalisation la plus simple est la sélection de la vue que vous souhaitez pour la représentation de l'objet référencé. Ceci est réalisé à l'aide de l'annotation @ReferenceView :Dans l'entité Invoice (facture), vous devez avoir défini une vue "Simple" :
Ainsi, au lieu d'afficher la vue par défaut de Invoice (qui montre toutes les membres de l'objet), OpenXava utilisera la vue suivante :
Personnalisation du cadre
Si vous combinez l'annotation @NoFrame avec des groupes, vous pouvez assembler visuellement une propriété qui ne fait pas partie de la référence avec celle-ci, par exemple :ce qui donnera le résultat suivant :
Action de recherche personnalisée
L'utilisateur peut rechercher une nouvelle valeur pour la référence simplement en entrant une nouvelle clé et lorsque le curseur quitte l'éditeur, les données de la référence sont récupérées et affichées. Par exemple. si l'utilisateur entre le chiffre "1" dans le champ numéro de la référence seller (vendeur), le champ nom (et les autres données) du vendeur identifié par "1" sera automatiquement rempli. De même, l'utilisateur peut aussi cliquer sur la loupe, dans quel cas, il accédera à une liste dans laquelle il pourra filtrer, trier, etc., et marquer l'objet souhaité.Afin de définir une action de recherche personnalisée, il faut utiliser l'annotation @SearchAction de cette manière :
La logique de l'action MySearchAction est de votre ressort. Vous pouvez par exemple affiner l'action de recherche standard en filtrant la liste de références comme ceci :
Vous pouvez en apprendre plus sur les actions au chapitre 7.
Condition for search list (reference, new in v4m4)
Please, translate this section to FrenchWhen the user clicks in the lantern he go to a list where he can filter, order, etc, and mark the wished object. You can use @SearchAction to overwrite completely this behavior, though if you only want to set a custom condition for the list, then using @SearchListCondition is faster. The above example can be rewritten as following:
Note as you do not need to create any action.
Action de création personnalisée
Si vous n'utilisez pas l'annotation @NoCreate, l'utilisateur bénéficiera d'un lien lui permettant de créer un nouvel objet. Par défaut, lorsque un utilisateur active ce lien, une vue par défaut de l'objet référencé est affichée dans laquelle il peut entrer les valeurs puis cliquer sur un bouton qui crée l'objet. Si vous souhaitez définir des actions personnalisées (parmi lesquels votre action personnalisée de création) dans le formulaire utilisé pour créer un nouvel objet, vos devez avoir défini un contrôleur dont le nom est identique au composant mais avec le suffixe Creation. Si OpenXava trouve ce contrôleur, il l'utilise à la place de celui par défaut utilisé pour la création de l'objet référencé. Par exemple, vous pouvez définir dans votre fichier controllers.xml :Dans cet exemple, lorsque l'utilisateur clique sur le lien 'create' (créer), l'utilisateur sera dirigé vers la vue par défaut de Warehouse (entrepôt) et toutes les actions du contrôleur WarehouseCreation seront permises. Si vous avez une action appelée 'new' (nouveau), elle sera exécutée automatiquement avant les autres. Elle peut être utilisée pour initialiser la vue utilisée pour la création du nouvel objet.
Action de modification personnalisée
Si l'annotation @NoModify est absente, l'utilisateur aura une action lui permettant de modifier l'objet référencé. Par défaut, lorsque l'utilisateur choisi cette option, une vue par défaut de l'objet est affichée et l'utilisateur peut modifier les valeurs avant de cliquer sur le bouton de mise à jour. Si vous souhaitez définir des actions personnalisées (parmi lesquels votre action personnalisée de modification) dans le formulaire utilisé pour modifier un objet, vos devez avoir défini un contrôleur dont le nom est identique au composant mais avec le suffixe Modification. Si OpenXava trouve ce contrôleur, il l'utilise à la place de celui par défaut utilisé pour la modification de l'objet référencé. Par exemple, vous pouvez définir dans votre fichier controllers.xml :Dans cet exemple, lorsque l'utilisateur clique sur le lien 'modify' (modifier), l'utilisateur sera dirigé vers la vue par défaut de Warehouse (entrepôt) et toutes les actions du contrôleur WarehouseModification seront permises. Si vous avez une action appelée 'search' (recherche), elle sera exécutée automatiquement avant les autres. Elle est utilisée pour initialiser la vue utilisée pour la modification de l'objet.
Liste de descriptions (Combos)
Avec l'annotation @DescriptionsList, vous pouvez indiquer à OpenXava de présenter les références comme des listes de descriptions (actuellement une liste déroulante). Ceci est utile lorsqu'il n'y a que peu d'éléments et que ces éléments possèdent un nom ou une description significative. La syntaxe est la suivante :- descriptionProperties (optionnel). La ou les propriétés à afficher dans la liste. Si cet attribut n'est pas spécifié, la propriété appelée description, descripcion, name ou nombre est assumée. Si l'objet référencé n'a pas de propriété appelée par l'un de ces noms, l'attribut descriptionProperties est requis. Il est possible de mettre plus d'une propriété séparées par des virgules. Pour l'utilisateur finale, les valeurs sont agrégées.
- depends (optionnel). Cet attribut est utilisé en combinaison avec condition. Il permet que le contenu de la liste dépende d'une autre valeur affichée dans la vue principale (si vous indiquez simplement le nom d'un membre) ou de la même vue (si vous indiquez this. suivi du nom du membre).
- condition (optionnel). Permet de spécifier une condition (dans un style SQL) pour filtrer les valeurs qui sont présentées dans la liste de descriptions.
- orderByKey (optionnel). Par défaut, les données sont triées par la description. Toutefois, si vous mettez cette attribut à true (vrai), la liste sera triée selon la clé.
- order (optionnel). Permet de spécifier un tri (dans un style SQL) pour les valeurs affichées dans la liste de descriptions.
- forTabs (optionnel): Please, translate to French: (New in v4m4) Allows to specify multiple tab names separated by commas. If any of the properties from descriptionProperties is in any of these tabs the filter part will be shown with a description list.
- notForTabs (optionnel): Please, translate to French: (New in v4m4) Allows to specify multiple tab names separated by commas. If any of the properties from descriptionProperties is in any of these tabs the filter part will continue to be displayed like a plain property.
L'utilisation la plus simple est la suivante :qui affiche les référence des entrepôts disponibles (Warehouse) ainsi :
Dans cette exemple, tous les entrepôts sont affichés, même si en réalité la condition de base (baseCondition) et le filtre (filter) sont spécifiés dans l'annotation @Tab de l'entité Warehouse. Vous pouvez apprendre plus sur la gestion des listes dans le chapitre 5.
Si vous souhaitez, par exemple, afficher une liste déroulante (combo) avec des catégories (Family) de produits et que lorsque l'utilisateur en choisit une, une autre liste déroulante soit remplie avec des sous-catégories (Subfamily) de la catégorie choisie, une implémentation de cette fonctionnalité pourrait ressembler à ceci :
Deux listes déroulantes sont affichées, l'une avec toutes les catégories et l'autre vide. Lorsque l'utilisateur choisi une catégorie, la seconde liste et remplie avec toutes les sous-catégories.
Dans le cas de la catégorie (Family), la propriété description de Family est utilisée puisque la propriété par défaut à afficher est 'description' ou 'name'. les données sont triées par clé et non par description (1). Dans le cas de la sous-catégorie (Subfamily) (2), le lien pour créer une nouvelle sous-catégorie n'est pas montré et la propriété à afficher est description (ce qui pourrait par ailleurs être omis).
Avec l'attribut depends (4) vous rendez cette liste déroulante dépendante de la référence family. Lorsqu'une modification de la référence family survient dans l'interface graphique, la liste de descriptions est remplie en appliquant la condition déclarée par l'attribut condition (5) qui envoie la nouvelle valeur de family. Les entrées sont triés par la propriété description en ordre descendant (6).
Dans les attributs condition et order, vous placez le nom de la propriété à l'intérieur de ${} et les arguments sont déclarés par un point d'interrogation (?). Les opérateurs de comparaison sont les opérateurs SQL.
New in v3.0.3: (Please, translate to French) Qualified properties are allowed for condition and order even if they are not in descriptionProperties. That is, you can write a condition like this:
(Please, translate to French) You can define complex conditions using JPQL (new in v4.5, before v4.5 SQL was used):
(Please, translate to French) As you can see in the example above, with JPQL (new in v4.5) you can use e.propertyName as alternative to ${propertyName}.
Vous pouvez aussi spécifier plusieurs propriétés qui font partie de la description :
Dans ce cas, la concaténation des propriétés description, level (niveau) et name (nom) sera utilisée dans la liste déroulante. Vous pouvez également voir l'utilisation de propriétés qualifiées (level.description).
Si vous utilisez l'annotation @ReadOnly dans une référence annotée avec @DescriptionList, la description (dans ce cas, level.description + name) est affichée comme une simple propriété textuelle à la place de la liste déroulante.
Evénement de modification de la valeur d'une référence
Si vous avez besoin de réagir à un changement de valeur de la référence, vous pouvez déclarer une action ainsi:Dans ce cas, votre action est à l'écoute du changement du numéro de transporteur (carrier). Le code à exécuter est le suivant :
L'action implémente l'interface IOnChangePropertyAction par le biais de l'héritage de OnChangePropertyBaseAction (1), même si c'est une référence. La nouvelle valeur de la propriété clé de la référence est passée comme paramètre, dans ce cas, carrier.number. Le reste est identique au fonctionnement pour les propriétés.
Recherche d'une référence lors de l'événement de modification
L'utilisateur peu chercher la valeur d'une référence simplement en entrant sa clé. Par exemple, s'il existe une référence à l'entité Subfamiliy (sous-catégorie), l'utilisateur peut entrer le numéro de sous-catégorie et les données de celle-ci sont automatiquement chargées dans l'interface utilisateur. Ceci est réalisé à l'aide de l'action par défaut qui exécute la recherche à la modification de la valeur. Vous pouvez spécifier votre propre action de recherche lorsque la clé change en utilisant l'annotation @OnChangeSearch, comme ceci :L'action est exécutée pour effectuer la recherche à la place de l'action standard lorsque l'utilisateur change le numéro de sous-catégorie. Le code qui est exécuté est le suivant :
L'action implémente l'interface IOnchangePropertyAction par le biais de l'héritage de OnChangeSearchAction (1), même si c'est une référence. La nouvelle valeur de la propriété clé de la référence est passée comme paramètre, dans ce cas, subfamily.number. Ceci est un exemple d'affinage du comportement d'une recherche après modification, car elle hérite de OnChangeSearchAction, qui est l'action par défaut pour la recherche, et appelle super.execute(). Il est également possible de créer une action normale en étendant OnChangePropertyBaseAction par exemple, surchargeant complètement la logique de recherche.
Choosing an editor (reference, new in v3.1.3)
Please, translate this section to FrenchAn editor display the reference to the user and allows him to edit its value. By default, the editor OpenXava uses for references is a detailed view inside a frame (the standard way) or a combo (if you use @DescriptionsList), but you can specify your own editor to display a concrete reference using @Editor.
For example, if you have a reference to a Color entity and you want to display it in some particular entity or view using a custom user interface, such as a radio buttons group with available colors, you can do it in this way:
In this case the ColorRadioButtons editor will be used for displaying/editing, instead of the default one. You must define your ColorRadioButton editor in the xava/editors.xml file of your project:
<editor name="ColorRadioButtons" url="colorRadioButtonsEditor.jsp"/>Also you have to write the JSP code for your editor in colorRadioButonsEditor.jsp.This feature is for changing the editor for a concrete reference in a concrete entity only, or even only in one view of that entity (using @Editor(forViews=)). If you want to change the editor for all references to certain entity type at application level then it's better to configure it using xava/editors.xml file.
Learn more on Editors for references section of chapter 9.
Personnalisation des collections
Vous pouvez influencer l'aspect visuel et le comportement d'une collection @OneToMany/@ManyToMany dans une vue en utilisant les annotations suivantes :Please translate to French: And the next annotations for a @ElementCollection (new in v5.0):
Toutes ces annotations suivent les règles pour les annotations de vues et sont optionnelles. OpenXava assume toujours une valeur correcte lorsqu'elles sont omises.
- @CollectionView (OX) La vue de l'objet référencé (un élément de la collection) qui est utilisée pour afficher le détail. Par défaut, la vue par défaut est utilisée.
- @ReadOnly (OX) Si vous utilisez cette annotation, l'utilisateur final ne peut que voir les éléments de la collection. Il ne peut ni ajouter, ni supprimer, ni modifier les éléments de la collection.
- @EditOnly (OX) Si vous utilisez cette annotation, l'utilisateur peut modifier des éléments existants, mais pas ajouter ou supprimer des éléments de la collection.
- @NoCreate (OX) Si vous utilisez cette annotation, l'utilisateur n'aura pas le lien pour créer de nouveaux objets du type référencé. Ceci ne s'applique pas aux collections embarquées.
- @NoModify (OX) Si vous utilisez cette annotation, l'utilisateur n'aura pas le lien pour modifier les objets du type référencé. Ceci ne s'applique pas aux collections embarquées.
- @AsEmbedded (OX) Par défaut, les collections embarquées (avec un type de cascade REMOVE ou ALL) permettent à l'utilisateur de créer et modifier des éléments, tandis que les collections d'entités traditionnelles ne permettent que de choisir une entité existante pour l'ajouter (ou l'enlever de) à la collection. Si vous utilisez l'annotation @AsEmbedded, la collection se comporte comme une collection embarquée même si elle n'a pas les types de cascade REMOVE ou ALL, permettant ainsi à l'utilisateur d'ajouter ou éditer des objets directement. Cette annotation n'a pas d'effet pour les collections embarquées.
- @ListProperties (OX) Indique les propriétés à afficher dans la liste de la collection. Vous pouvez qualifier les propriétés. Par défaut, toutes les propriétés persistantes de l'objet référencé sont affichées (à l'exclusion des références et des propriétés calculées). Please, translate the next sentences to French: The suffix + (new in v4.1) can be added to a property name to show the sum of the column at bottom, like in the tabs. The column summation is not allowed in calculated collections and element collections.
- @RowStyle (OX) Permet de donner un style spécial à certaines lignes. Cette annotation fonctionne de la même manière que pour la vue liste des modules. Elle ne fonctionne pas pour les collections calculées et il est possible de définir plusieurs annotation @RowStyle pour chaque vue.
- @EditAction (OX) Permet de définir une action personnalisée pour initier l'édition d'un élément de la collection. Cette action est celle affichée dans chaque ligne de la collection, si la collection est éditable. Une seule annotation @EditAction par vue est permise.
- @ViewAction (OX) Permet de définir une action personnalisée pour la visualisation d'un objet de la collection. Cette action est celle affichée dans chaque ligne de la collection, si la collection est en lecture seule. Une seule annotation @ViewAction par vue est permise.
- @NewAction (OX) Permet de définir une action personnalisée pour initier l'ajout d'un nouvel objet dans la collection. Cette action est celle exécutée après un click sur le lien 'Ajouter'. Une seule annotation @NewAction par vue est permise.
- @SaveAction (OX) Permet de définir une action personnalisée pour initier l'enregistrement d'un objet de la collection. Cette action est celle exécutée après un click sur le lien 'Enregistrer le détail'. Une seule annotation @SaveAction par vue est permise.
- @HideDetailAction (OX) Permet de définir une action personnalisée pour fermer la vue de détail d'un objet de la collection. Cette action est celle exécutée après un click sur le lien 'Fermer' or closing the dialog. Une seule annotation @HideDetailAction par vue est permise.
- @RemoveAction (OX) Permet de définir une action personnalisée pour supprimer un objet de la collection. Cette action est celle exécutée après un click sur le lien 'Supprimer le détail'. Une seule annotation @RemoveAction par vue est permise.
- @RemoveSelectedAction (OX) Permet de définir une action personnalisée pour supprimer de la collection un ensemble d'objets sélectionnés dans la liste. Cette action est celle exécutée après un click sur le lien 'Supprimer la sélection'. Une seule annotation @RemoveSelectedAction par vue est permise.
- @ListAction (OX) Permet d'ajouter des actions à la vue liste de la collection, en général des actions dont le cadre est la collection entière. Il est possible de définir plusieurs actions de ce type pour chaque vue.
- @RowAction (OX): Please, translate to French: (New in v4.6) To add actions in list mode associated to each row; these actions are not present in the button bar of the collection, but only in the rows. It's possible to define several @RowAction for each view.
- @DetailAction (OX) Permet d'ajouter des actions à la vue de détail des éléments de la collection, en général des actions dont le cadre est l'objet en cours d'édition. Il est possible de définir plusieurs actions de ce type pour chaque vue.
- @OnSelectElementAction (OX): (New in v3.1.2) (Please, translate this to French) To define an action to be executed when an element of the collection is selected or unselected. It's possible to define several @OnSelectElementAction for each view.
- @Editor (OX): (New in v3.1.3) (Please, translate this to French) Name of the editor to use for displaying the collection in this view. The editor must be declared in OpenXava/xava/default-editors.xml or xava/editors.xml of your project.
- @SearchListCondition (OX): (New in v4m4) (Please, translate this to French) Condition to be used for listing the selectable elements that can be added to the collection. It does not apply to embedded collections.
- @Tree (OX): Please, translate to French: (New in v4m4) To indicate that this collection will be displayed using a tree instead of a list.
- @Collapsed (OX): Please, translate to French: (New in v5.0) The collection will be shown collapsed for the indicated views. Visually this means that the frame surrounding the collection view will be initially closed. Later the user will be able to set his preferences by clicking on the expansion icon.
Si vous n'utilisez aucune de ces annotations, celle-ci est affichée en utilisant les propriétés persistantes dans le mode liste et la vue par défaut pour présenter le détail de l'objet. Toutefois, dans les scénarios usuels, les propriétés de la liste et du détail sont spécifiés :La définition ci-dessus est affichée ainsi :
Remarquez comment les propriétés qualifiées sont utilisées dans la liste des propriétés (exemple seller.level.description).
Lorsque l'utilisateur clique sur
La même vue est utilisée lorsque l'utilisateur clique sur
en cliquant pour voir un détail, l'affichage suivant sera généré :
Please, translate to French: Element collections (new in v5.0) do not use @ReferenceView because the data is editable in the collection directly, like an spreadsheet. However, you can use @ListProperties. If you define an element collection in this way:
Please, translate to French: You get the next user interface:
Actions d'affichage/édition personnalisées
S'applique à collection @OneToMany/@ManyToManyIl est facile d'affiner le comportement du lien
Dans le fichier controllers.xml, il faut déclarer le contrôleur Invoices.editDetail :
Il faut encore le code de l'action :
Dans cet exemple, vous ne faites qu'affiner car votre action étend EditElementInCollectionAction (1). Dans ce cas, vous ne spécifiez qu'une valeur par défaut pour la propriété remarks (remarques). Notez que pour accéder à la vue qui affiche le détail, vous pouvez utiliser la méthode getCollectionElementView() (2).
Il est aussi possible d'enlever l'action d'édition de l'interface utilisateur de cette manière :
Il suffit de spécifier une chaîne de caractère vide comme valeur de l'action. Toutefois, dans la plupart des cas, il est plus aisé de définir la collection avec l'annotation @ReadOnly.
La technique pour affiner une action de vue (l'action pour chaque ligne de la liste) est la même sauf qu'elle est définie par l'annotation @ViewAction au lieu de @EditAction.
Actions de liste et rang personnalisées
S'applique à collection @OneToMany/@ManyToManyPlease, translate the next paragraph to French
Use @ListAction to define actions that applies to entire collection and @RowAction (new in v4.6) to define actions for each row. @ListAction and @RowAction are very alike, indeed they are coded in the same way, the difference is that the @ListActions are shown in the button bar while the @RowActions are shown in each row. @ListActions can be also shown in each row if they are defined as in-each-row="true" in controllers.xml.
This is an example:
A présent, le nouveau lien est affiché pour l'utilisateur :
Vous avez aussi besoin de définir l'action dans le fichier controllers.xml :
Et le code de l'action :
L'action étend CollectionBaseAction (1). De cette façon, vous pouvez utiliser des méthodes comme getSelectedObjects() (2) qui retourne une collection avec les objets sélectionnés par l'utilisateur. D'autres méthodes utiles sont également disponibles comme getObjects() (tous les éléments de la collection), getMapValues() (les valeurs de la collection dans un format dictionnaire) et getMapsSelectedValues()(les éléments sélectionnés dans un format dictionnaire).
Please, translate the next sentence to French: In the case of @RowAction, getSelectedObjects() and getMapsSelectedValues() return an unique element, the one of the row of the action, even if the row is not checked.
Comme dans le cas des actions de détail (voir section suivante), vous pouvez utiliser getCollectionElementView(). Il est aussi possible d'utiliser des actions pour le mode liste comme actions de liste personnalisées.
Actions de liste et rang par défaut
S'applique à collection @OneToMany/@ManyToManySi vous voulez ajouter quelques actions de liste personnalisées pour toutes les collections de votre application, vous pouvez créer un contrôleur appelé DefaultListActionsForCollections dans le fichier xava/controllers.xml comme ceci:
De cette manière, toutes les collections auront les actions du contrôleur Print (pour l'exportation vers Excel et la génération de rapports PDF) et votre propre ExportAsXMLAction. Ceci a le même effet que l'annotation @ListAction (référez-vous à la section sur les actions de liste personnalisées) mais s'applique à toutes les collections en une seule fois.
Please, translate the next sentence to French: If you want to define default row actions (@RowAction) you can define the controller DefaultRowActionsForCollections (new in v4.6).
Cette fonction ne s'applique pas aux collections calculées.
Actions de détail personnalisées
S'applique à collection @OneToMany/@ManyToManyIl est également possible d'ajouter des actions personnalisées aux vues de détail utilisées pour modifier chaque élément de la collection. L'annotation @DetailAction permet de réaliser ceci. Ces actions sont applicables à un seul élément de la collection à la fois. Par exemple :
De cette manière, l'utilisateur bénéficiera d'un nouveau lien dans la vue de détail de l'élément de la collection, ici View Product (Voir le produit) :
Vous devez préalablement définir l'action dans le fichier controllers.xml de votre projet :
Et puis écrire le code de votre action :
Vous pouvez observer que la classe de l'action hérite de CollectionElementViewBaseAction (1) et bénéficie donc d'un accès à la vue qui affiche l'élément courant par la méthode getCollectionElementView() (2). La vue principale est également accessible en utilisant la méthode getView() (3) ou getParentView() (since v4m5). Dans le chapitre 7, vous pouvez avoir plus de détails sur l'écriture des actions.
En outre, en utilisant la vue renvoyée par la méthode getCollectionElementView(), vous pouvez ajouter et supprimer depuis le code des actions de détail et de liste avec les méthodes addDetailAction(), removeDetailAction(), addListAction() et removeListAction() (référez vous à la documentation de l'API de org.openxava.view.View.
Affinage du comportement par défaut de la vue de collection
S'applique à collection @OneToMany/@ManyToManyEn utilisant les annotations @NewAction, @SaveAction, @HideDetailAction, @RemoveAction et @RemoveSelectedAction, vous pouvez affiner le comportement par défaut d'une vue de collection. Par exemple, si vous voulez redéfinir le comportement de l'action d'enregistrer un détail, vous pouvez définir votre vue ainsi :
Bien entendu, vous devez également définir l'action DeliveryDetail.save (Détail de livraison.enregistrer) dans le fichier controllers.xml de votre projet :
Et finalement écrire l'implémentation de l'action pour procéder à l'enregistrement :
Le cas le plus commun est d'étendre le comportement par défaut en faisant hériter votre action de la classe originale qui enregistre un élément de la collection (1), c'est-à-dire l'action SaveElementInCollectionElement puis en faisant appel à la méthode super.execute() (2) depuis votre propre méthode execute() avant d'insérer votre code.
Il est également possible d'enlever n'importe laquelle de ces actions de l'interface graphique. Par exemple, vous pouvez définir une collection de cette manière :
Dans ce cas, l'action pour supprimer les éléments sélectionnés de la collectionne sera pas présente dans l'interface utilisateur. Comme vous pouvez le constater, il faut déclarer une chaîne de caractères vide comme nom de l'action.
Action when a collection element is selected (new in v3.1.2)
S'applique à collection @OneToMany/@ManyToManyPlease, translate this section to French
You can define an action to be executed when a collection element is selected or unselected. This is accomplished using the @OnSelectElementAction annotation. For example, imagine that you have a collection just like this one:
And you want that when a row is selected the value of the selectedIngredientSize field in the user interface will be updated. Let's code it.
First you have to annotate your collection:
In this simple way (1), and thanks to the @OnSelectElementAction annotation, you say that when the user clicks on the checkbox of the collection row the Formula.onSelectIngredient action will be executed. This action is declared in controllers.xml, in this way:
Now, only remains the code of the OnSelectIngredientAction class:
The easiest way to implement the action is extending from OnSelectElementBaseAction, this allows you to access to the property selected (by means of isSelected(), 2) that indicates wheter the user has selected or unselected the row; and row (using getRow()) that indicates the row number of the affected collection element.
Choosing an editor (collection, new in v3.1.3)
S'applique à collection @OneToMany/@ManyToMany et @ElementCollectionPlease, translate this section to French
An editor display the collection to the user and allows him to edit its values. By default, the editor OpenXava uses for collections is a list that shows the data in a tabular fashion, allowing to order, filter and paging, but you can specify your own editor to display a concrete collection using @Editor.
For example, if you have a collection of Customer entities and you want to display it in some particular entity or view using a custom user interface, such as a simple list of names, you can do it in this way:
In this case the CustomersNames editor will be used for displaying/editing, instead of the default one. You must define your CustomersNames editor in the xava/editors.xml file of your project:
<editor name="CustomersNames" url="customersNamesEditor.jsp"/>Also you have to write the JSP code for your editor in customersNamesEditor.jsp.This feature is for changing the editor for a concrete collection in a concrete entity only, or even only in one view of that entity (using @Editor(forViews=)). If you want to change the editor for all collections to certain entity type at application level then it's better to configure it using xava/editors.xml file.
Learn more on Editors for collections section of chapter 9.
Condition for search list (collection, new in v4m4)
S'applique à collection @OneToMany/@ManyToManyPlease, translate this section to French
You can specify a condition to be applied to the list of items available for selection. In the case of non-embedded collections. By using @SearchListCondition you can define a condition only applicable to the search list, furthermore, you can use it along with the forViews and notForViews property to define different criteria for different views (1) as shown in the following code snippet.
Displaying collections as a tree (new in v4m4)
S'applique à collection @OneToMany/@ManyToManyPlease, translate this section to French
It is possible to render a collection as a tree:
Selecting the TreeView editor (1) is enough for displaying the collection as a tree. The properties defined as ids are used for making the label of the treeview, but you can define different properties by specifying the @ListProperties (2) annotation. The items are displayed in the natural order of the collection of the order defined by @OrderBy (3). If the collection entity contains a string property named "path", the treeview editor render the tree using its content; if another property should be used instead, then you must use the @Tree annotation (4) to indicate which property to use.
As you can see in the table, the tree is made by concatenating the id separated by "/". Sibling items must have the same path. The editor takes care of the creation and modification of the path property. This will look like this:
Please translate the next paragraphs to French
The full syntax for @Tree is:
Total properties (new in v4.3)
S'applique à collection @OneToMany/@ManyToMany and @ElementCollectionPlease, translate this section to French
Inside @ListProperties you can define, between square brakets, a set of properties of the parent entity of the collection to be shown in the footer of the collection as total values. That is, if you define a collection in this way:
You get:
Total properties can be used for both persistent and calculated collections. You can add total properties to any property of @ListProperties and they can be of any type, not just numbers. These total properties are from the container entity so you have to use the reference to the container entity as prefix, that is, the prefix of the total properties must match with the mappedBy reference in the case of persistent collections.
Propriétés transientes pour la gestion de l'interface utilisateur
Avec l'annotation @Transient (JPA), vous déclarez une propriété qui n'est pas enregistrée dans la base de donnée, mais que vous souhaitez montrer à l'utilisateur. Vous pouvez utiliser cette fonctionnalité pour fournir des contrôles d'interface utilisateur pour leur permettre de gérer son interface graphique. Un exemple :Notez que la syntaxe est exactement la même que dans le cas d'une propriété standard d'une entité. Vous pouvez même utiliser un enum et un calculateur par défaut (@DefaultValueCalculator). Après avoir défini la propriété, vous pouvez l'utiliser dans la vue comme d'habitude, par exemple avec l'annotation @OnChange ou en le rendant membre d'une vue.
Actions de vues
En plus d'associer des actions à des propriétés, des références ou des collections, vous pouvez aussi ajouter des actions arbitraires à l'intérieur de votre vue, à n'importe quel endroit. Pour ce faire, vous utilisez le nom qualifié de l'action en utilisant de parenthèses () comme suffixe, de cette manière :L'effet visuel sera celui-ci :
Le lien 'Change name label' (Changer le libellé du nom) exécutera l'action Customer.changeNameLabel lorsque l'utilisateur cliquera dessus. Si la vue parente de l'action n'est pas éditable, l'action n'est pas affichée. Si vous souhaitez que l'action soit toujours présente, même si la vue n'est pas éditable, vous devez placer le mot-clé ALWAYS entre les parenthèses, comme ici :
La manière standard d'exposer des actions à l'utilisateur est d'utiliser des contrôleurs (actions dans les barres supérieures et/ou inférieures) afin que les contrôleurs soient réutilisables entre les vues, mais parfois, vous devrez avoir une action spécifique pour une vue, et vous souhaiterez l'afficher à l'intérieur de la vue (et non dans la barre d'actions). Pour ces cas, les actions de vue sont utiles. Plus sur les actions au chapitre 7.
Classes transientes : Uniquement pour créer des vues
Dans OpenXava, il n'est pas possible d'avoir une vue générée sans modèle. Ainsi, si vous souhaitez développer une interface utilisateur arbitraire, vous devez créer une classe, ne pas la déclarer comme entité et y définir votre vue.Une classe transiente n'est pas associée à une table de la base de données, typiquement elle n'est utilisée que pour l'affichage de l'interface graphique et n'est liée à aucune donnée de la base. Une exemple pourrait être le suivant :
Pour définir une classe de modèle transiente, vous n'avez qu'à définir une classe standard Java sans l'annotation @Entity. Vous ne spécifiez pas non plus les annotations de mapping objet-relationnel ni les propriétés comme clé.
Ainsi, vous pouvez développer un dialogue qui peut être utile, par exemple, pour imprimer un rapport des catégories de produits, filtrés par sous-catégorie.
Les classes transientes sont utilisées uniquement avec des modules de détail. (Please, translate the next sentence to French) You can use a transient class without defining a module because a default one is generated, however if you want to generate a portlet for your transient class you must define explicitly a module in application.xml.
Le paquet contenant le classes de modèle transientes doit être le même que celui des classes persistantes.
Avec cette simple astuce, vous pouvez utiliser OpenXava comme un générateur simple et flexible d'interfaces graphiques même si les données ne seront jamais enregistrées.